﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace CSConsoleTest
{
    enum ECalcOpCode
    {
        eOP_PLUS,
        eOP_MINUS,
        eOP_MULTIPLY,
        eOP_DIVIDE
    }

    class TestDelegate : BaseConsoleTest
    {
        public delegate int calcDelegate(int aArg1, int aArg2);
        public delegate void scheduleDelegate();

        public void printDescription()
        {
            Console.WriteLine("--- Delegate ---"); 
        }

        public void doTest()
        {
            Console.WriteLine("15 + 5 = {0}", calc(ECalcOpCode.eOP_PLUS, 15, 5));
            Console.WriteLine("15 - 5 = {0}", calc(ECalcOpCode.eOP_MINUS, 15, 5));
            Console.WriteLine("15 * 5 = {0}", calc(ECalcOpCode.eOP_MULTIPLY, 15, 5));
            Console.WriteLine("15 / 5 = {0}", calc(ECalcOpCode.eOP_DIVIDE, 15, 5));

            //delegate chain
            scheduleDelegate schedule = weakUp;
            schedule += andThen;
            schedule += haveBreakfast;
            schedule += andThen;
            schedule += goForAWalk;
            schedule += andThen;
            schedule += haveLunch;
            schedule += new scheduleDelegate(andThen);
            schedule += new scheduleDelegate(doCoding);
            schedule += delegate
            {
                Console.Write("Empty schedule"); 
            };
            Delegate.Combine(schedule, new scheduleDelegate(andThen));
            Delegate.Combine(schedule, new scheduleDelegate(haveDinner));
            Delegate.Combine(schedule, new scheduleDelegate(goToBed));

            Console.WriteLine("-Do schedule"); 
            schedule();
            Console.WriteLine();

            //Func
            Func<int, int, int> plusFunc = (aArg1, aArg2) => aArg1 + aArg2;
            
            ///Action
            Action<int, int> printPlusFunc = (aArg1, aArg2) => Console.WriteLine("{0} + {1} = {2}", aArg1, aArg2, aArg1 + aArg2);


        }

        public int calc(ECalcOpCode aOpCode, int aArg1, int aArg2)
        {
            calcDelegate calcMethod = getOperation(aOpCode);
            return calcMethod(aArg1, aArg2);
        }

        private calcDelegate getOperation(ECalcOpCode aOpCode)
        {
            switch (aOpCode)
            {
                case ECalcOpCode.eOP_PLUS :
                    return plus;
                case ECalcOpCode.eOP_MINUS:
                    return minus;
                case ECalcOpCode.eOP_MULTIPLY:
                    return multiply;
                case ECalcOpCode.eOP_DIVIDE:
                    return divide;
                default :
                    throw new InvalidOperationException("Operation " + aOpCode + " is invalid");
            }
        }

        private int plus(int aArg1, int aArg2)
        {
            return aArg1 + aArg2;
        }

        private int minus(int aArg1, int aArg2)
        {
            return aArg1 + aArg2;
        }

        private int multiply(int aArg1, int aArg2)
        {
            return aArg1 + aArg2;
        }

        private int divide(int aArg1, int aArg2)
        {
            return aArg1 + aArg2;
        }

        private void andThen()
        {
            Console.Write(" -> ");
        }

        private void weakUp()
        {
            Console.Write("Wake up");
        }

        private void haveBreakfast()
        {
            Console.Write("have breadfast");
        }

        private void goForAWalk()
        {
            Console.Write("go for a walk");
        }

        private void haveLunch()
        {
            Console.Write("have lunch");
        }

        private void doCoding()
        {
            Console.Write("coding");
        }

        private void haveDinner()
        {
            Console.Write("have dinner");
        }

        private void goToBed()
        {
            Console.Write("go to bed");
        }
    }

}
